#ifndef NIGHT_CORE
#define NIGHT_CORE

namespace night {

namespace detail {

template< typename E > struct Base {};

template< typename D, typename E > inline D & derived ( Base<E> & ref ) { return static_cast<D &> (ref); }
template< typename D, typename E > inline D const & derived ( Base<E> const & ref ) { return static_cast<D const &> (ref); }

template< typename D, typename E > inline D * derived ( Base<E> * ptr ) { return static_cast<D *> (ptr); }
template< typename D, typename E > inline D const * derived ( Base<E> const * ptr ) { return static_cast<D const *> (ptr); }

} // end namespace detail

namespace detail {

template< int src > struct int_c { static const int value = src; };

template< typename T, typename Dummy >
struct instance_first {
	typedef T type;
};

} // end namespace detail

namespace detail {

template< int cond, typename Then, typename Else > struct if_c { typedef Then type; };
template< typename Then, typename Else > struct if_c<0,Then,Else> { typedef Else type; };

template< typename T, typename S > struct is_same { static const int value = 0; };
template< typename T > struct is_same<T,T> { static const int value = 1; };

template< typename T > struct is_const { static const int value = 0; };
template< typename T > struct is_const<T const> { static const int value = 1; };


template< typename T > struct remove_ref { typedef T type; };
template< typename T > struct remove_ref< T & > { typedef T type; };

template< typename T > struct remove_const { typedef T type; };
template< typename T > struct remove_const< T const > { typedef T type; };

template< typename T >
struct remove_cref { typedef typename remove_ref<typename remove_const<T>::type>::type type; };


template< typename T > struct add_ref { typedef T & type; };
template< typename T > struct add_ref< T & > { typedef T & type; };

template< typename T > struct add_const { typedef T const type; };
template< typename T > struct add_const< T const > { typedef T const type; };

template< typename T >
struct add_cref { typedef typename add_ref<typename add_const<T>::type>::type type; };

} // end namespace detail


using detail::derived;

template< typename Type >
struct by_val {
	typedef Type type;
	typedef Type value_type;
	typedef Type const & param_type;
};

template< typename Type >
struct by_ref {
	typedef Type type;
	typedef Type & value_type;
	typedef Type & param_type;
};

template< typename Type >
struct by_cref {
	typedef Type type;
	typedef Type const & value_type;
	typedef Type const & param_type;
};


typedef int size_type;

struct empty {};

template<int n> 
struct index {
	static const int value = n;
};

const index<0> _i = {};
const index<1> _j = {};
const index<2> _k = {};
const index<3> _l = {};
const index<4> _m = {};
const index<5> _n = {};
const index<6> _o = {};
const index<7> _p = {};

} // end namespace night

#endif
